/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package asset.load;

import com.jme3.animation.Bone;
import com.jme3.animation.Skeleton;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import asset.Skel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import util.math.Convert;
import util.xml.XML;

/**
 *
 * @author
 */
public class LoadSkel {

    public static Skel load(String file) throws Exception {
        Worker w = new Worker(file);
        w.load();
        return w.getSkel();
    }

    private static class Worker {

        String file;
        Skel skel;
               //
        List<Bone> boneList;
        Map<String, Integer> nameToIndex;
        int boneIndex;

        private Worker(String file) {
            this.file = file;
            this.boneList = new ArrayList<>();
            this.nameToIndex = new HashMap<>();
            this.boneIndex = 0;
            
        }

        public Skel getSkel() {
            return skel;
        }

        public void load() throws Exception {
           
            Document doc = XML.openDocument(file);
            
            for (Node rootBone = doc.getFirstChild().getFirstChild(); rootBone != null; rootBone = rootBone.getNextSibling()) {
                recur(rootBone);
            }
            
            Skeleton skeleton = new Skeleton(boneList.toArray(new Bone[0]));
            skeleton.setBindingPose();
            skel = new Skel(skeleton, nameToIndex);
        }

        private Bone recur(Node boneNode) {
            int index = boneIndex;

            boneIndex += 1;

            String name = XML.getStr(boneNode, "name");

            Node locNode = boneNode.getFirstChild();
            Vector3f loc = Convert.toVector3f(XML.getFloatArray(locNode, "x", "y", "z"));

            Node rotNode = locNode.getNextSibling();
            Quaternion rot = Convert.toQuaternion(XML.getFloatArray(rotNode, "w", "x", "y", "z")).normalizeLocal();

            //-------------------------
            
            Bone bone = new Bone(name);
            bone.setBindTransforms(loc, rot, new Vector3f(1, 1, 1));

            boneList.add(bone);
            nameToIndex.put(name, index);

            //-------------------------
            
            Node childrenNode = rotNode.getNextSibling();
            if (childrenNode != null) {
                for (Node childNode = childrenNode.getFirstChild(); childNode != null; childNode = childNode.getNextSibling()) {
                    Bone child = recur(childNode);
                    bone.addChild(child);
                }
            }

            return bone;
        }
    }
}
